
set PS_NAME   xlnx_bd_soc

create_bd_design "xlnx_bd_soc"

##################################################################
# DESIGN PROCs
##################################################################

# Procedure to create entire design; Provide argument to make
# procedure reusable. If parentCell is "", will use root.
proc create_root_design { parentCell } {

  variable script_folder
  variable design_name

  if { $parentCell eq "" } {
     set parentCell [get_bd_cells /]
  }

  # Get object for parentCell
  set parentObj [get_bd_cells $parentCell]
  if { $parentObj == "" } {
     catch {common::send_msg_id "BD_TCL-100" "ERROR" "Unable to find parent cell <$parentCell>!"}
     return
  }

  # Make sure parentObj is hier blk
  set parentType [get_property TYPE $parentObj]
  if { $parentType ne "hier" } {
     catch {common::send_msg_id "BD_TCL-101" "ERROR" "Parent <$parentObj> has TYPE = <$parentType>. Expected to be <hier>."}
     return
  }

  # Save current instance; Restore later
  set oldCurInst [current_bd_instance .]

  # Set parent object as current
  current_bd_instance $parentObj


  # Create interface ports

  set axi_interconnect [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_interconnect:2.1 axi_interconnect ]
  set_property -dict [ list \
    CONFIG.NUM_MI {3} \
    CONFIG.NUM_SI {2} \
  ] $axi_interconnect


  # Create ROM
  set blk_mem_rom [ create_bd_cell -type ip -vlnv xilinx.com:ip:blk_mem_gen:8.4 blk_mem_rom ]

  set currDir [pwd]
  puts "$currDir"
  puts "----------------------------------------------------------------------------"
  set coeFile "$currDir/inst_ram.coe"

  set_property -dict [list \
    CONFIG.Memory_Type {Single_Port_ROM} \
    CONFIG.Write_Depth_A {4096} \
    CONFIG.use_bram_block {BRAM_Controller} \
    CONFIG.EN_SAFETY_CKT {false} \
    CONFIG.Coe_File {../../../../../../inst_ram.coe} \
    CONFIG.Load_Init_File {true} \
  ] $blk_mem_rom


  set axi_rom_ctrl [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_bram_ctrl:4.1 axi_rom_ctrl ]
  set_property CONFIG.SINGLE_PORT_BRAM {1} $axi_rom_ctrl

  connect_bd_intf_net [get_bd_intf_pins blk_mem_rom/BRAM_PORTA] [get_bd_intf_pins axi_rom_ctrl/BRAM_PORTA]

  
  # Create RAM
  set blk_mem_ram [ create_bd_cell -type ip -vlnv xilinx.com:ip:blk_mem_gen:8.4 blk_mem_ram ]

  set_property -dict [list \
    CONFIG.Write_Depth_A {512} \
    CONFIG.use_bram_block {BRAM_Controller} \
    CONFIG.EN_SAFETY_CKT {false} \
  ] $blk_mem_ram

  set axi_ram_ctrl [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_bram_ctrl:4.1 axi_ram_ctrl ]
  set_property CONFIG.SINGLE_PORT_BRAM {1} $axi_ram_ctrl

  connect_bd_intf_net [get_bd_intf_pins $blk_mem_ram/BRAM_PORTA] [get_bd_intf_pins $axi_ram_ctrl/BRAM_PORTA]


  # DDR4 create_bd_port -dir O -type clk clk_100M
  set ddr4_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:ddr4:2.2 ddr4_0 ]
  apply_board_connection -board_interface "ddr4_sdram_c1_083" -ip_intf "$ddr4_0/C0_DDR4" -diagram "xlnx_bd_soc"
  #"design_1" 
  apply_board_connection -board_interface "default_250mhz_clk1" -ip_intf "$ddr4_0/C0_SYS_CLK" -diagram "xlnx_bd_soc"   
  set_property -dict [list \
    CONFIG.RESET_BOARD_INTERFACE {reset} \
    CONFIG.C0.DDR4_AxiIDWidth {8} \
  ] $ddr4_0

  apply_bd_automation -rule xilinx.com:bd_rule:board -config { Board_Interface {reset ( FPGA Reset ) } Manual_Source {Auto}}  [get_bd_pins ddr4_0/sys_rst]


  # Clock 10MHz
  set clk_wiz [ create_bd_cell -type ip -vlnv xilinx.com:ip:clk_wiz:6.0 clk_wiz ]
  set_property -dict [list \
    CONFIG.CLKOUT1_JITTER {132.683} \
    CONFIG.CLKOUT1_PHASE_ERROR {87.180} \
    CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {50.000} \
    CONFIG.MMCM_CLKFBOUT_MULT_F {12.000} \
    CONFIG.MMCM_CLKOUT0_DIVIDE_F {24.000} \
    CONFIG.MMCM_DIVCLK_DIVIDE {1} \
    CONFIG.USE_LOCKED {false} \
    CONFIG.USE_RESET {false} \
    CONFIG.CLK_OUT1_PORT {clk_50M} \
    CONFIG.CLKOUT2_JITTER {102.086} \
    CONFIG.CLKOUT2_PHASE_ERROR {87.180} \
    CONFIG.CLKOUT2_REQUESTED_OUT_FREQ {200.000} \
    CONFIG.CLKOUT2_USED {true} \
    CONFIG.CLKOUT3_JITTER {107.567} \
    CONFIG.CLKOUT3_PHASE_ERROR {87.180} \
    CONFIG.CLKOUT3_REQUESTED_OUT_FREQ {150.000} \
    CONFIG.CLKOUT3_USED {true} \
    CONFIG.CLK_OUT2_PORT {clk_200M} \
    CONFIG.CLK_OUT3_PORT {clk_150M} \
    CONFIG.MMCM_CLKOUT1_DIVIDE {6} \
    CONFIG.MMCM_CLKOUT2_DIVIDE {8} \
    CONFIG.NUM_OUT_CLKS {3} \
  ] $clk_wiz

  connect_bd_net [get_bd_pins $ddr4_0/addn_ui_clkout1] [get_bd_pins clk_wiz/clk_in1]
  

  # UART
  set axi_uart [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_uart16550:2.0 axi_uart ]
  apply_board_connection -board_interface "rs232_uart" -ip_intf "axi_uart/UART" -diagram  "xlnx_bd_soc"
  #"design_1" 


  # Reset 100M
  set rst_ddr4_0_100M [ create_bd_cell -type ip -vlnv xilinx.com:ip:proc_sys_reset:5.0 rst_ddr4_0_100M ]
  connect_bd_net [get_bd_pins $rst_ddr4_0_100M/slowest_sync_clk] [get_bd_pins $ddr4_0/addn_ui_clkout1]
  connect_bd_net [get_bd_pins $rst_ddr4_0_100M/ext_reset_in] [get_bd_pins $ddr4_0/c0_ddr4_ui_clk_sync_rst]

  # Create FLASH
  set axi_flash [create_bd_cell -type ip -vlnv xilinx.com:ip:axi_quad_spi:3.2 axi_flash]
  set_property -dict [list \
    CONFIG.C_TYPE_OF_AXI4_INTERFACE {1} \
    CONFIG.C_DUAL_QUAD_MODE {1} \
    CONFIG.C_USE_STARTUP_INT {1} \
    CONFIG.QSPI_BOARD_INTERFACE {spi_flash} \
  ] [get_bd_cells axi_flash]
  apply_board_connection -board_interface "spi_flash" -ip_intf "axi_flash/SPI_1" -diagram "xlnx_bd_soc" 

  # JTAG 
  set jtag_axi [ create_bd_cell -type ip -vlnv xilinx.com:ip:jtag_axi:1.2 jtag_axi ]
  set_property -dict [ list \
    CONFIG.M_AXI_ADDR_WIDTH {64} \
    CONFIG.M_AXI_DATA_WIDTH {32} \
    CONFIG.M_AXI_ID_WIDTH {3} \
    CONFIG.M_HAS_BURST {0} \
    CONFIG.RD_TXN_QUEUE_LENGTH {8} \
    CONFIG.WR_TXN_QUEUE_LENGTH {8} \
  ] $jtag_axi

  connect_bd_intf_net [get_bd_intf_pins jtag_axi/M_AXI] -boundary_type upper [get_bd_intf_pins axi_interconnect/S01_AXI]
  connect_bd_net [get_bd_pins jtag_axi/aresetn] [get_bd_pins rst_ddr4_0_100M/peripheral_aresetn]
  connect_bd_net [get_bd_pins jtag_axi/aclk] [get_bd_pins ddr4_0/addn_ui_clkout1]

  connect_bd_net [get_bd_pins axi_interconnect/S01_ACLK] [get_bd_pins ddr4_0/addn_ui_clkout1]
  connect_bd_net [get_bd_pins axi_interconnect/S01_ARESETN] [get_bd_pins rst_ddr4_0_100M/peripheral_aresetn]

  # AXI Smart Connection
  set axi_smc [create_bd_cell -type ip -vlnv xilinx.com:ip:smartconnect:1.0 axi_smc]
  set_property -dict [list \
    CONFIG.NUM_CLKS {3} \
    CONFIG.NUM_MI {3} \
    CONFIG.NUM_SI {1} \
  ] $axi_smc


  # Connection wire
  connect_bd_intf_net [get_bd_intf_pins axi_smc/S00_AXI] -boundary_type upper [get_bd_intf_pins axi_interconnect/M00_AXI]
  connect_bd_net [get_bd_pins axi_uart/s_axi_aclk] [get_bd_pins ddr4_0/addn_ui_clkout1]
  connect_bd_net [get_bd_pins axi_uart/s_axi_aresetn] [get_bd_pins rst_ddr4_0_100M/peripheral_aresetn]
  connect_bd_net [get_bd_pins axi_interconnect/M00_ACLK] [get_bd_pins ddr4_0/addn_ui_clkout1]
  connect_bd_net [get_bd_pins axi_interconnect/M00_ARESETN] [get_bd_pins rst_ddr4_0_100M/peripheral_aresetn]

  connect_bd_intf_net -boundary_type upper [get_bd_intf_pins axi_interconnect/M01_AXI] [get_bd_intf_pins axi_uart/S_AXI]
  # connect_bd_net [get_bd_pins axi_uart/s_axi_aclk] [get_bd_pins ddr4_0/addn_ui_clkout1]
  # connect_bd_net [get_bd_pins axi_uart/s_axi_aresetn] [get_bd_pins rst_ddr4_0_100M/peripheral_aresetn]
  connect_bd_net [get_bd_pins axi_interconnect/M01_ACLK] [get_bd_pins ddr4_0/addn_ui_clkout1]
  connect_bd_net [get_bd_pins axi_interconnect/M01_ARESETN] [get_bd_pins rst_ddr4_0_100M/peripheral_aresetn]

  connect_bd_intf_net [get_bd_intf_pins axi_flash/AXI_FULL] -boundary_type upper [get_bd_intf_pins axi_interconnect/M02_AXI]
  connect_bd_net [get_bd_pins axi_interconnect/M02_ACLK] [get_bd_pins ddr4_0/addn_ui_clkout1]
  connect_bd_net [get_bd_pins axi_interconnect/M02_ARESETN] [get_bd_pins rst_ddr4_0_100M/peripheral_aresetn]


  connect_bd_net [get_bd_pins axi_interconnect/ACLK] [get_bd_pins ddr4_0/addn_ui_clkout1]
  connect_bd_net [get_bd_pins axi_interconnect/ARESETN] [get_bd_pins rst_ddr4_0_100M/peripheral_aresetn]

  connect_bd_net [get_bd_pins axi_interconnect/S00_ACLK] [get_bd_pins ddr4_0/addn_ui_clkout1]
  connect_bd_net [get_bd_pins axi_interconnect/S00_ARESETN] [get_bd_pins rst_ddr4_0_100M/peripheral_aresetn]

  connect_bd_net [get_bd_pins axi_smc/aclk] [get_bd_pins ddr4_0/c0_ddr4_ui_clk]
  connect_bd_net [get_bd_pins axi_smc/aresetn] [get_bd_pins rst_ddr4_0_100M/peripheral_aresetn]

  connect_bd_intf_net -boundary_type upper [get_bd_intf_pins axi_smc/M00_AXI] [get_bd_intf_pins ddr4_0/C0_DDR4_S_AXI]
  connect_bd_intf_net [get_bd_intf_pins axi_smc/M01_AXI] [get_bd_intf_pins axi_rom_ctrl/S_AXI]
  connect_bd_intf_net [get_bd_intf_pins axi_smc/M02_AXI] [get_bd_intf_pins axi_ram_ctrl/S_AXI]

  connect_bd_net [get_bd_pins axi_ram_ctrl/s_axi_aclk] [get_bd_pins ddr4_0/addn_ui_clkout1]
  connect_bd_net [get_bd_pins axi_rom_ctrl/s_axi_aclk] [get_bd_pins ddr4_0/addn_ui_clkout1]

  connect_bd_net [get_bd_pins axi_smc/aclk1] [get_bd_pins ddr4_0/addn_ui_clkout1]
  connect_bd_net [get_bd_pins axi_smc/aclk2] [get_bd_pins ddr4_0/addn_ui_clkout1]

  connect_bd_net [get_bd_pins axi_ram_ctrl/s_axi_aresetn] [get_bd_pins rst_ddr4_0_100M/peripheral_aresetn]
  connect_bd_net [get_bd_pins axi_rom_ctrl/s_axi_aresetn] [get_bd_pins rst_ddr4_0_100M/peripheral_aresetn]
  connect_bd_net [get_bd_pins ddr4_0/c0_ddr4_aresetn] [get_bd_pins rst_ddr4_0_100M/peripheral_aresetn]

  connect_bd_net [get_bd_pins axi_flash/ext_spi_clk] [get_bd_pins ddr4_0/addn_ui_clkout1]
  connect_bd_net [get_bd_pins axi_flash/s_axi4_aclk] [get_bd_pins ddr4_0/addn_ui_clkout1]
  connect_bd_net [get_bd_pins axi_flash/s_axi4_aresetn] [get_bd_pins rst_ddr4_0_100M/peripheral_aresetn]

  # Create Ports
  set s_axi [ create_bd_intf_port -mode Slave -vlnv xilinx.com:interface:aximm_rtl:1.0 s_axi ]
  set_property -dict [list \
    CONFIG.HAS_REGION \
    [get_property CONFIG.HAS_REGION [get_bd_intf_pins axi_interconnect/xbar/S00_AXI]] \
    CONFIG.NUM_READ_OUTSTANDING \
    [get_property CONFIG.NUM_READ_OUTSTANDING [get_bd_intf_pins axi_interconnect/xbar/S00_AXI]] \
    CONFIG.NUM_WRITE_OUTSTANDING \
    [get_property CONFIG.NUM_WRITE_OUTSTANDING [get_bd_intf_pins axi_interconnect/xbar/S00_AXI]]\
    ] [get_bd_intf_ports s_axi]
  connect_bd_intf_net [get_bd_intf_pins axi_interconnect/S00_AXI] [get_bd_intf_ports s_axi]

  create_bd_port -dir O -type clk clk_100M
  connect_bd_net [get_bd_pins /ddr4_0/addn_ui_clkout1] [get_bd_ports clk_100M]

  # make_bd_pins_external  [get_bd_pins clk_wiz/clk_10M]
  # set_property name clk_10M [get_bd_ports clk_10M_0]
  create_bd_port -dir O -type clk clk_50M
  connect_bd_net [get_bd_pins /clk_wiz/clk_50M] [get_bd_ports clk_50M]

  create_bd_port -dir O -type clk clk_200M
  connect_bd_net [get_bd_pins /clk_wiz/clk_200M] [get_bd_ports clk_200M]

  create_bd_port -dir O -type clk clk_150M
  connect_bd_net [get_bd_pins /clk_wiz/clk_150M] [get_bd_ports clk_150M]

  create_bd_port -dir O -type rst core_reset_b
  connect_bd_net [get_bd_pins /rst_ddr4_0_100M/peripheral_aresetn] [get_bd_ports core_reset_b]

  create_bd_port -dir I -type rst vio_cpu_reset
  connect_bd_net [get_bd_pins /rst_ddr4_0_100M/aux_reset_in] [get_bd_ports vio_cpu_reset]
  set_property -dict [list CONFIG.POLARITY ACTIVE_HIGH] [get_bd_ports vio_cpu_reset]

  create_bd_port -dir O -from 0 -to 0 -type rst peripheral_aresetn
  connect_bd_net [get_bd_pins /rst_ddr4_0_100M/peripheral_aresetn] [get_bd_ports peripheral_aresetn]
  
  # # 20M AXI
  # set_property -dict [list \
  #   CONFIG.ADDR_WIDTH 50 \
  #   CONFIG.DATA_WIDTH 128 \
  #   CONFIG.FREQ_HZ 20000000 \
  #   CONFIG.HAS_QOS 0 \
  #   CONFIG.ID_WIDTH 5\
  # ] [get_bd_intf_ports s_axi]

  # 100M AXI
  set_property -dict [list \
    CONFIG.ADDR_WIDTH 48 \
    CONFIG.DATA_WIDTH 128 \
    CONFIG.FREQ_HZ 100000000 \
    CONFIG.HAS_QOS 0 \
    CONFIG.ID_WIDTH 8\
  ] [get_bd_intf_ports s_axi]

  # # CLK=20M
  # connect_bd_net [get_bd_pins axi_interconnect/S00_ACLK] [get_bd_pins clk_wiz/clk_20M]

  # CLK=10M
  # connect_bd_net [get_bd_pins axi_interconnect/S00_ACLK] [get_bd_pins clk_wiz/clk_10M]
  
  create_bd_port -dir O -type intr uart_int
  connect_bd_net [get_bd_pins /axi_uart/ip2intc_irpt] [get_bd_ports uart_int]

  # Create Address Mapping
  assign_bd_address [get_bd_addr_segs {ddr4_0/C0_DDR4_MEMORY_MAP/C0_DDR4_ADDRESS_BLOCK }]
  assign_bd_address [get_bd_addr_segs {axi_rom_ctrl/S_AXI/Mem0 }]
  assign_bd_address [get_bd_addr_segs {axi_ram_ctrl/S_AXI/Mem0 }]
  assign_bd_address [get_bd_addr_segs {axi_uart/S_AXI/Reg }]
  assign_bd_address [get_bd_addr_segs {axi_flash/aximm/MEM0 }]

  set_property offset 0x000001C000000 [get_bd_addr_segs {s_axi/SEG_axi_rom_ctrl_Mem0}]
  set_property offset 0x000001C060000 [get_bd_addr_segs {s_axi/SEG_axi_ram_ctrl_Mem0}]
  set_property offset 0x000001FF00000 [get_bd_addr_segs {s_axi/SEG_axi_uart_Reg}]
  
  set_property range 64K [get_bd_addr_segs {s_axi/SEG_axi_rom_ctrl_Mem0}]
  set_property offset 0x0000100000000 [get_bd_addr_segs {s_axi/SEG_ddr4_0_C0_DDR4_ADDRESS_BLOCK}]
  set_property range 4G [get_bd_addr_segs {s_axi/SEG_ddr4_0_C0_DDR4_ADDRESS_BLOCK}]
  set_property offset 0x0000080000000 [get_bd_addr_segs {s_axi/SEG_axi_flash_MEM0}]
  set_property range 2G [get_bd_addr_segs {s_axi/SEG_axi_flash_MEM0}]

  assign_bd_address -target_address_space /jtag_axi/Data [get_bd_addr_segs ddr4_0/C0_DDR4_MEMORY_MAP/C0_DDR4_ADDRESS_BLOCK] -force
  delete_bd_objs [get_bd_addr_segs jtag_axi/Data/SEG_axi_flash_MEM0]
  delete_bd_objs [get_bd_addr_segs jtag_axi/Data/SEG_axi_ram_ctrl_Mem0]
  delete_bd_objs [get_bd_addr_segs jtag_axi/Data/SEG_axi_rom_ctrl_Mem0]
  delete_bd_objs [get_bd_addr_segs jtag_axi/Data/SEG_axi_uart_Reg]

  exclude_bd_addr_seg [get_bd_addr_segs axi_ram_ctrl/S_AXI/Mem0] -target_address_space [get_bd_addr_spaces jtag_axi/Data]
  exclude_bd_addr_seg [get_bd_addr_segs axi_rom_ctrl/S_AXI/Mem0] -target_address_space [get_bd_addr_spaces jtag_axi/Data]
  exclude_bd_addr_seg [get_bd_addr_segs axi_uart/S_AXI/Reg] -target_address_space [get_bd_addr_spaces jtag_axi/Data]
  exclude_bd_addr_seg [get_bd_addr_segs axi_flash/aximm/MEM0] -target_address_space [get_bd_addr_spaces jtag_axi/Data]

  set_property offset 0x0000000100000000 [get_bd_addr_segs {jtag_axi/Data/SEG_ddr4_0_C0_DDR4_ADDRESS_BLOCK}]
  set_property range 4G [get_bd_addr_segs {jtag_axi/Data/SEG_ddr4_0_C0_DDR4_ADDRESS_BLOCK}]


  # Restore current instance
  current_bd_instance $oldCurInst

  validate_bd_design
  save_bd_design
}
# End of create_root_design()


##################################################################
# MAIN FLOW
##################################################################

create_root_design ""


